//
//  GLSLViewController.swift
//  ZSceneDemo
//
//  Created by 张鑫 on 2020/9/8.
//  Copyright © 2020 www.lionaitech.com. All rights reserved.
//

import UIKit

import SceneKit

extension GeometrySourceViewController {
    
    func sourceAndElement() {
        
        /// 创建顶点坐标
        let vertex:[Float] = [-3, 3,1,
                              3, 3,1,
                              3,-3,1,
                              -3,-3,1]
        /// 创建纹理坐标
        let texture:[Float] = [0,0,
                               1,0,
                               1,1,
                               0,1]
        /// 法线索引
        let normal:[Float] = [0,0,1,
                              0,0,1,
                              0,0,1,
                              0,0,1]
        /// 颜色坐标
        let color:[Float] = [1,0,0,
                             0,1,0,
                             0,0,1,
                             1,1,1]
        /// 创建顶点索引
        let indices:[GLint] = [0,1,2,0,2,3]
        
        // 负责加载顶点数据,纹理数据,颜色数据,纹理坐标
        /// 创建接受顶点的对象
        let vertexSource = SCNGeometrySource(data: getData(array: vertex),
                                             semantic: .vertex,
                                             vectorCount: 4,
                                             usesFloatComponents: true,
                                             componentsPerVector: 3,
                                             bytesPerComponent: MemoryLayout<Float>.size,
                                             dataOffset: 0,
                                             dataStride: MemoryLayout<Float>.size * 3)
        /// 创建纹理坐标对象
        let textureSource = SCNGeometrySource(data: getData(array: texture),
                                              semantic: .texcoord,
                                              vectorCount: 4,
                                              usesFloatComponents: true,
                                              componentsPerVector: 2,
                                              bytesPerComponent: MemoryLayout<Float>.size,
                                              dataOffset:0,
                                              dataStride: MemoryLayout<Float>.size * 2)
        /// 法线坐标对象
        let normalSource = SCNGeometrySource(data: getData(array: normal),
                                             semantic: .normal,
                                             vectorCount: 4,
                                             usesFloatComponents: true,
                                             componentsPerVector: 3,
                                             bytesPerComponent: MemoryLayout<Float>.size,
                                             dataOffset: 0,
                                             dataStride: MemoryLayout<Float>.size * 3)
        /// 颜色对象
        let colorSource = SCNGeometrySource(data: getData(array: color),
                                            semantic: .color,
                                            vectorCount: 4,
                                            usesFloatComponents: true,
                                            componentsPerVector: 3,
                                            bytesPerComponent:  MemoryLayout<Float>.size,
                                            dataOffset: 0,
                                            dataStride: MemoryLayout<Float>.size*3)
        //负责加载索引数据
        /// 顶点索引
        let indicesElement = SCNGeometryElement(data: getData(array: indices),
                                                primitiveType: .triangles,
                                                primitiveCount: indices.count / 3,
                                                bytesPerIndex: MemoryLayout<GLint>.size)
        
        let geometry = SCNGeometry(sources: [vertexSource, textureSource, normalSource, colorSource], elements: [indicesElement])
        
        sceneView?.scene?.rootNode.addChildNode(SCNNode(geometry: geometry))
    }
    
    func getData<T>(array:[T]) -> Data{
        let data: UnsafeMutableRawPointer = malloc(MemoryLayout<T>.size * array.count)
        data.initializeMemory(as: T.self, from: array, count: array.count)
        return Data(bytesNoCopy: data, count: MemoryLayout<T>.size * array.count, deallocator: Data.Deallocator.free)
    }
    
    func simpleSourceAndElement() {
        /// 创建顶点坐标
        let vertex = [SCNVector3(-3, 3,1),
                      SCNVector3( 3, 3,1),
                      SCNVector3( 3,-3,1),
                      SCNVector3(-3,-3,1)]
        // MARK: 纹理着色时与顶点坐标一一对应
        /**
         1. 纹理坐标使用的屏幕的坐标（即：左上角为原点）
         2. 纹理坐标范围是 0～1，大于1后边缘的像素会被拉伸
         3. 使用纹理时，需要注意方向转换
         4. 多个顶点几何体时，需要考虑纹理材料的切分
         5. 多个顶点几何体时，需要考虑重复顶点的复用问题
         6. 纹理坐标不会作用于color source
         */
        /// 创建纹理坐标
        let texture = [CGPoint(x: 0,y: 0),
                       CGPoint(x: 1.5,y: 0),
                       CGPoint(x: 1,y: 1),
                       CGPoint(x: 0,y: 1),
        ]
        /// 法线索引
        let normal = [SCNVector3(0,0,1),
                      SCNVector3(0,0,1),
                      SCNVector3(0,0,1),
                      SCNVector3(0,0,1)]
        /// 颜色坐标
        let color:[Float] = [1,0,0,
                             0,1,0,
                             0,0,1,
                             1,1,1]
        
        // MARK: 顶点顺序注意事项
        // 1. 顶点坐标索引需要时 int32 类型的其他类型数据长度（猜测底层只认 int32，使用int64得到索引不对）
        // 2. 在 .triangles 模式下，颜色显示都是在顶点逆时针方向的那一面
        // 3. 在 .triangleStrip 模式下，颜色显示，首个面是逆时针方向，第二个是顺时针方向，后面就是交替的
        /// 创建顶点索引
        let indices:[GLint] = [1,2,0,3]
        
        // 负责加载顶点数据,纹理数据,颜色数据,纹理坐标
        /// 创建接受顶点的对象
        let vertexSource = SCNGeometrySource(vertices: vertex)
        
        /// 创建纹理坐标对象
        let textureSource = SCNGeometrySource(textureCoordinates: texture)
        
        /// 法线坐标对象
        let normalSource = SCNGeometrySource(normals: normal)
        
        /// 颜色对象
        let colorSource = SCNGeometrySource(data: getData(array: color),
                                            semantic: .color,
                                            vectorCount: 4,
                                            usesFloatComponents: true,
                                            componentsPerVector: 3,
                                            bytesPerComponent:  MemoryLayout<Float>.size,
                                            dataOffset: 0,
                                            dataStride: MemoryLayout<Float>.size*3)
        //负责加载索引数据
        /// 顶点索引
        let indicesElement = SCNGeometryElement(indices: indices, primitiveType: .triangleStrip)
        
        let geometry = SCNGeometry(sources: [vertexSource, textureSource, normalSource], elements: [indicesElement])
        geometry.materials.first?.diffuse.contents = "art.scnassets/SunSysSource/earth-diffuse.jpg"
        
        sceneView?.scene?.rootNode.addChildNode(SCNNode(geometry: geometry))
    }
    
    
    
    
}
